import java.io.IOException;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;


public class PowerOutputMarkhovFull {

	public static void main(String[] args) throws IOException{
		//Initialize system parameters
		int num_states=20;
		double state_size=15;
		
		
		
		//Declare containers to hold results
		TreeMap<String,TreeMap<String,Integer>> markhovMap = new TreeMap<String,TreeMap<String,Integer>>(new NumbersThenWordsComparator());
		
		//Initialize containers
		for(int i=0;i<num_states;i++){
			markhovMap.put("S"+i, new TreeMap<String,Integer>(new NumbersThenWordsComparator()));
			for(int j=0;j<num_states;j++){
				markhovMap.get("S"+i).put("S"+j, 0);
			}
		}
		//Import Data
		//ArrayList<ArrayList<String>> powerOutput = CSVIO.readFile("output.csv");
		ArrayList<ArrayList<String>> forecastData = CSVIO.readFile("harbec_data_output_row_april_may_2012.csv");
		
		//Parse imported data and add hits to the container
		double previousOutput=0;
		double currentOutput=0;
		for(ArrayList<String> curColumn : forecastData){
			
			for(String entry: curColumn){
				//System.out.println(entry);
				
				try{
					currentOutput= Double.parseDouble(entry);
					
					int current_output_belongs_to_state= (int)(currentOutput/state_size);
					int previous_output_belongs_to_state=(int)(previousOutput/state_size);
					int current_state_transition_Count= markhovMap.get("S"+previous_output_belongs_to_state).get("S"+current_output_belongs_to_state);
					int updated_current_state_transition_Count =current_state_transition_Count+1;
					markhovMap.get("S"+previous_output_belongs_to_state).put("S"+current_output_belongs_to_state,updated_current_state_transition_Count);
					
					previousOutput=currentOutput;
				}catch(NumberFormatException nfe){
					
				}
							
				
			}
			
			
		}
		//Print column labels
		for(String colLabel: markhovMap.keySet()){
			System.out.print("\t"+colLabel);
		}
		//print state values
		System.out.println();
		for(int i=0;i<markhovMap.size();i++){
			System.out.print("\t"+/*i*state_size+*/"->"+((i+1)*state_size));
		}
		//praint column labels
		System.out.println("\n");
		for(String colLabel: markhovMap.keySet()){
			System.out.print("\t"+colLabel);
		}
		//print the data in the container
		System.out.println();
		for(String rowLabel: markhovMap.keySet()){
			System.out.print(rowLabel+"\t");
			TreeMap<String, Integer> rowMap=markhovMap.get(rowLabel);
			for(String col:rowMap.keySet()){
				System.out.print(rowMap.get(col)+"\t");
			}
			System.out.println();
			
		}
		System.out.println();
		//Print column labels
		for(String colLabel: markhovMap.keySet()){
			System.out.print("\t"+colLabel);
		}
		System.out.println();
		//Calculate probabilities and print them
		DecimalFormat df = new DecimalFormat("#.000");
		for(String row: markhovMap.keySet()){
			System.out.print(row+"\t");
			TreeMap<String, Integer> rowMap=markhovMap.get(row);
			int rowSum =0;
			for(int val :rowMap.values()){
				rowSum=rowSum+val;
			}
			for(String col:rowMap.keySet()){
				if(rowSum!=0){
					System.out.print(df.format((rowMap.get(col)/((double)rowSum)))+"\t");
				}else{
					System.out.print("x\t");
				}
			}
			System.out.println();
			
		}
		//Print column labels
		
		//print data in the container
		
	}
}

class NumbersThenWordsComparator implements Comparator {
	private final boolean isDigit(char ch) {
		return ch >= 48 && ch <= 57;
	}

	/**
	 * Length of string is passed in for improved efficiency (only need to
	 * calculate it once)
	 **/
	private final String getChunk(String s, int slength, int marker) {
		StringBuilder chunk = new StringBuilder();
		char c = s.charAt(marker);
		chunk.append(c);
		marker++;
		if (isDigit(c)) {
			while (marker < slength) {
				c = s.charAt(marker);
				if (!isDigit(c))
					break;
				chunk.append(c);
				marker++;
			}
		} else {
			while (marker < slength) {
				c = s.charAt(marker);
				if (isDigit(c))
					break;
				chunk.append(c);
				marker++;
			}
		}
		return chunk.toString();
	}

	public int compare(Object o1, Object o2) {
		if (!(o1 instanceof String) || !(o2 instanceof String)) {
			return 0;
		}
		String s1 = (String) o1;
		String s2 = (String) o2;

		int thisMarker = 0;
		int thatMarker = 0;
		int s1Length = s1.length();
		int s2Length = s2.length();

		while (thisMarker < s1Length && thatMarker < s2Length) {
			String thisChunk = getChunk(s1, s1Length, thisMarker);
			thisMarker += thisChunk.length();

			String thatChunk = getChunk(s2, s2Length, thatMarker);
			thatMarker += thatChunk.length();

			// If both chunks contain numeric characters, sort them numerically
			int result = 0;
			if (isDigit(thisChunk.charAt(0)) && isDigit(thatChunk.charAt(0))) {
				// Simple chunk comparison by length.
				int thisChunkLength = thisChunk.length();
				result = thisChunkLength - thatChunk.length();
				// If equal, the first different number counts
				if (result == 0) {
					for (int i = 0; i < thisChunkLength; i++) {
						result = thisChunk.charAt(i) - thatChunk.charAt(i);
						if (result != 0) {
							return result;
						}
					}
				}
			} else {
				result = thisChunk.compareTo(thatChunk);
			}

			if (result != 0)
				return result;
		}

		return s1Length - s2Length;
	}
}